package com.example.customview.cutdown

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.RectF
import android.util.AttributeSet
import android.view.View
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.lifecycleScope
import com.android.baselibrary.utils.dp2px
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlin.math.min

/**
 * 圆形倒计时
 */
class CircleDownView @JvmOverloads constructor(
    context: Context, attributeSet: AttributeSet? = null,
    defaultStyle: Int = 0
) : View(context, attributeSet, defaultStyle) {
    private val mBgPaint = Paint()
    private val mProgressPaint = Paint()
    private val mTextPaint = Paint()
    private var mRadius = dp2px(100).toFloat()
    private var mProgressRadius = 80f
    private var mCenterX = 0f
    private var mCenterY = 0f
    private var mCurrentAngle = 0f
    private var mMaxAngle = 360f
    private var mText = "0%"

    private var mRect = RectF()

    init {
        mBgPaint.run {
            style = Paint.Style.FILL_AND_STROKE
            color = Color.GRAY
            isAntiAlias = true
        }
        mProgressPaint.run {
            style = Paint.Style.STROKE
            color = Color.RED
            isAntiAlias = true
            isDither = true
            strokeCap = Paint.Cap.ROUND
            strokeWidth = dp2px(10).toFloat()

        }
        mTextPaint.run {
            style = Paint.Style.STROKE
            color = Color.RED
            isAntiAlias = true
            textSize = dp2px(20).toFloat()
        }
    }

    fun startProgress() {
        if (context is FragmentActivity) {
            cutDownTime(60, (context as FragmentActivity).lifecycleScope, next = {
                mCurrentAngle = ((60 - it) / 60f) * mMaxAngle
                mText = "${(((60 - it) / 60f) * 100).toInt()}%"
                invalidate()
            }, finished = {
                mCurrentAngle = mMaxAngle
            })
        }
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mCenterX = (w / 2).toFloat()
        mCenterY = (h / 2).toFloat()
        val minW = min(w, h)
        mRadius = (minW - dp2px(10).toFloat()) / 2
        mProgressRadius = mRadius
        mRect.set(
            dp2px(5).toFloat(),
            dp2px(5).toFloat(),
            minW - dp2px(10).toFloat() / 2,
            minW - dp2px(10).toFloat() / 2
        )

    }

    override fun onDraw(canvas: Canvas) {

        canvas.drawCircle(mCenterX, mCenterY, mRadius, mBgPaint)

        canvas.drawArc(mRect, -90f, mCurrentAngle, false, mProgressPaint)

        val baseLineY = (mCenterY - (mProgressPaint.descent() + mProgressPaint.ascent()) / 2)

        val rectF = Rect()
        mTextPaint.getTextBounds(mText,0,mText.length,rectF)

        canvas.drawText(mText, mCenterX-rectF.width()/2, baseLineY, mTextPaint)


    }

    fun cutDownTime(
        maxTime: Int,
        coroutineScope: CoroutineScope,
        next: (int: Int) -> Unit,
        finished: () -> Unit
    ) {

        flow<Int> {
            for (i in maxTime.downTo(0)) {
                emit(i)
                if (i != 0) {
                    delay(1000)
                }
            }
        }.flowOn(Dispatchers.Main)
            .onEach {
                next.invoke(it)
            }.onCompletion {
                if (it == null) {
                    finished()
                }
            }.launchIn(coroutineScope)


    }


}